package org.example.Proxy;

import cn.hutool.core.lang.Console;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponse;

// HttpProxyClientHandler 继承自 ChannelInboundHandlerAdapter，
// 它是 Netty 网络编程框架中的一个适配器类，使得我们只需要覆写自己关心的方法。
public class HttpProxyClientHandler extends ChannelInboundHandlerAdapter {

    // 声明一个 ChannelHandlerContext 对象，表示当前 Channel 的处理上下文，
    // 主要用于在网络事件中进行数据的读取、写入和传递等操作。
    private final ChannelHandlerContext clientCtx;

    // 构造方法，参数是 ChannelHandlerContext，通过构造方法传递当前的处理上下文。
    public HttpProxyClientHandler(ChannelHandlerContext clientCtx) {
        this.clientCtx = clientCtx;
    }

    // 重写 channelRead 方法，该方法在 Channel 读取到数据时被触发。
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 判断读取到的数据是否是 HttpResponse 类型。
        Console.log(ctx);
        Console.log(msg);
        if (msg instanceof HttpResponse) {
            HttpResponse response = (HttpResponse) msg;
            // 如果 HttpResponse 的头信息中包含 'Connection' 字段，则移除它，
            // 因为我们想要保持与客户端的连接。
            if (response.headers().contains(HttpHeaderNames.CONNECTION)) {
                response.headers().remove(HttpHeaderNames.CONNECTION);
            }
            // 将处理过的 HttpResponse 转发给客户端。
            clientCtx.writeAndFlush(response).addListener((ChannelFutureListener) future -> {
                // 如果写入成功，则继续从目标服务器读取数据。
                if (future.isSuccess()) {
                    ctx.channel().read();
                } else {
                    // 如果写入失败，则关闭连接。
                    future.channel().close();
                }
            });
        }
        // 如果读取到的数据是 HttpContent 类型（如：文件块或其他数据流）。
        else if (msg instanceof HttpContent) {
            HttpContent content = (HttpContent) msg;
            // 将 HttpContent 转发给客户端。
            clientCtx.writeAndFlush(content).addListener((ChannelFutureListener) future -> {
                // 如果写入失败，则关闭连接。
                if (!future.isSuccess()) {
                    ctx.channel().close();
                }
            });
        } else {

        }
    }
}